<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="DGNnQ" id="DGNnQ"><span data-lake-id="u2a96daec" id="u2a96daec">典型回答</span></h1>
  <p data-lake-id="ub45eda1b" id="ub45eda1b"><br></p>
  <p data-lake-id="u9f950e85" id="u9f950e85"><span data-lake-id="u99a7c1f1" id="u99a7c1f1">UUID和自增主键ID是作为数据库主键比较常用的方式。使用这两个做主键各自都有优缺点。</span></p>
  <p data-lake-id="u9e392215" id="u9e392215"><span data-lake-id="u28ac3743" id="u28ac3743">​</span><br></p>
  <h4 data-lake-id="RkdLk" id="RkdLk"><span data-lake-id="ue6f169a1" id="ue6f169a1">UUID</span></h4>
  <p data-lake-id="uc9661f47" id="uc9661f47"><br></p>
  <p data-lake-id="uf44d9620" id="uf44d9620"><span data-lake-id="ub85132f1" id="ub85132f1">UUID 是一个 128 位长的唯一标识符，通常以字符串形式表示。它可以使用不同的算法生成，比如基于时间戳的 UUID（version 1）和随机数生成的 UUID（version 4）等。</span></p>
  <p data-lake-id="ufd7f0959" id="ufd7f0959"><br></p>
  <p data-lake-id="u0dedebd5" id="u0dedebd5"><span data-lake-id="u02a4295b" id="u02a4295b">​</span><br></p>
  <p data-lake-id="ue9fce199" id="ue9fce199"><span data-lake-id="ucd1eb7e0" id="ucd1eb7e0">他的优点是：</span></p>
  <p data-lake-id="u570e3c8f" id="u570e3c8f"><span data-lake-id="u169f5c7c" id="u169f5c7c">​</span><br></p>
  <ul list="ub0118c45">
   <li fid="ub34fb22a" data-lake-id="u84693f63" id="u84693f63"><strong><span data-lake-id="udecde7c8" id="udecde7c8">全局唯一</span></strong><span data-lake-id="uebc27293" id="uebc27293">：使用不同的算法生成，</span><strong><span data-lake-id="u63e646de" id="u63e646de">几乎可以保证</span></strong><span data-lake-id="u074d9ce9" id="u074d9ce9">在全球范围内唯一，避免了多台机器之间主键冲突的问题。</span></li>
   <li fid="ub34fb22a" data-lake-id="u06a78e51" id="u06a78e51"><strong><span data-lake-id="u961d2e1f" id="u961d2e1f">不可预测性</span></strong><span data-lake-id="uae4c3efe" id="uae4c3efe">：随机生成的 UUID 很难被猜测出来，对于需要保密性的应用场景较为适用。</span></li>
   <li fid="ub34fb22a" data-lake-id="uc4242dc6" id="uc4242dc6"><strong><span data-lake-id="uf2a81d63" id="uf2a81d63">分布式</span></strong><span data-lake-id="u86c9a73f" id="u86c9a73f">：由于可以在不同的机器上生成 UUID，因此可以用于分布式系统中。</span></li>
  </ul>
  <p data-lake-id="u3a4f8cfc" id="u3a4f8cfc"><span data-lake-id="u18a44a37" id="u18a44a37">​</span><br></p>
  <p data-lake-id="u4714701a" id="u4714701a"><span data-lake-id="u73bba1c4" id="u73bba1c4">UUID当做主键ID的话的缺点同样也有，如：</span></p>
  <p data-lake-id="u0d228c51" id="u0d228c51"><span data-lake-id="ud7cc2107" id="ud7cc2107">​</span><br></p>
  <ul list="ubae3f1b0">
   <li fid="ue9107748" data-lake-id="u9e84488e" id="u9e84488e"><span data-lake-id="u8505c62d" id="u8505c62d">存储空间比较大：UUID 通常以字符串形式存储，占用的存储空间比较大。</span></li>
   <li fid="ue9107748" data-lake-id="uf45a9652" id="uf45a9652"><span data-lake-id="u718552f2" id="u718552f2">不适合范围查询：因为不是自增的，所以在做范围查询的时候是不支持的。（后插入的UUID在排序时可能比前面的要小，在做范围查询的时候可能会出现数据重复或者漏数据的情况）</span></li>
   <li fid="ue9107748" data-lake-id="ufc9596c5" id="ufc9596c5"><span data-lake-id="uc8be64a2" id="uc8be64a2">不方便展示：主键ID有的时候会需要在系统间、或者前台页面展示，如果是UUID的话，就因为比较长、并且没有任何业务含义，所以不方便展示。</span></li>
  </ul>
  <ul list="u4043ab37">
   <li fid="ue9107748" data-lake-id="u735b87fd" id="u735b87fd"><span data-lake-id="ubf165eb9" id="ubf165eb9">查询效率低：</span></li>
  </ul>
  <ul list="u4043ab37" data-lake-indent="1">
   <li fid="ue9107748" data-lake-id="ue78d7e1f" id="ue78d7e1f"><span data-lake-id="u8623a260" id="u8623a260">在UUID列上创建索引，因为他很长，所以索引的大小会变得非常大。大的索引会占用更多的磁盘空间，导致缓存命中率下降，进而增加了磁盘I/O的需求。此外，大的索引还会导致查询时的内存开销增加。</span></li>
   <li fid="ue9107748" data-lake-id="u5d3240af" id="u5d3240af"><span data-lake-id="u1896f5cc" id="u1896f5cc">当使用UUID进行排序时，新的UUID值通常会插入到叶子节点的中间位置。这可能导致B+树的分裂和平衡操作频繁进行，从而增加了写入的开销。每次分裂或平衡都涉及到数据的重新排序和移动，这会影响查询的性能。</span></li>
  </ul>
  <p data-lake-id="uf20ade37" id="uf20ade37"><span data-lake-id="ue7495e7d" id="ue7495e7d">​</span><br></p>
  <h4 data-lake-id="BPBbs" id="BPBbs"><span data-lake-id="u51c0d3f8" id="u51c0d3f8">自增ID</span></h4>
  <p data-lake-id="ub499b290" id="ub499b290"><br></p>
  <p data-lake-id="udc8bbb98" id="udc8bbb98"><span data-lake-id="u8e9ce757" id="u8e9ce757">在 MySQL 中，可以通过设置 AUTO_INCREMENT 属性实现ID的自增长，通常可以用来作为主键ID。</span></p>
  <p data-lake-id="ua5c0b185" id="ua5c0b185"><span data-lake-id="u0d67755c" id="u0d67755c">​</span><br></p>
  <p data-lake-id="u978876a4" id="u978876a4"><span data-lake-id="u3f47c902" id="u3f47c902">使用自增ID做主键的好处是：</span></p>
  <p data-lake-id="ua7da70c0" id="ua7da70c0"><span data-lake-id="u1c7c5bdc" id="u1c7c5bdc">​</span><br></p>
  <ul list="u44db430e">
   <li fid="u240bf9ac" data-lake-id="u1834db2a" id="u1834db2a"><span data-lake-id="u8e8e4670" id="u8e8e4670">存储空间：ID是数字，所以占用的位数要比UUID小多了，所以在存储空间上也节省很多。</span></li>
   <li fid="u240bf9ac" data-lake-id="ucf792454" id="ucf792454"><span data-lake-id="ub976c411" id="ub976c411">查询效率：ID 是递增的，因此在使用 B+Tree 索引时，查询效率较高。</span></li>
   <li fid="u240bf9ac" data-lake-id="u6bed24ec" id="u6bed24ec"><span data-lake-id="u46129913" id="u46129913">方便展示：因为ID比较短，方便展示。</span></li>
   <li fid="u240bf9ac" data-lake-id="uf7951c6f" id="uf7951c6f"><span data-lake-id="ua22862ef" id="ua22862ef">分页方便：因为ID是连续自增的，所以在分页的时候，可以通过ID解决深度分页的问题。</span></li>
  </ul>
  <p data-lake-id="ub4ff44e6" id="ub4ff44e6"><span data-lake-id="u5cb33a98" id="u5cb33a98">​</span><br></p>
  <p data-lake-id="u64c2318c" id="u64c2318c"><span data-lake-id="ud0975ffe" id="ud0975ffe">但是，使用自增主键做主键ID也存在一定的问题：</span></p>
  <p data-lake-id="uc2401c62" id="uc2401c62"><br></p>
  <ul list="u60c8c679">
   <li fid="u291560ef" data-lake-id="uf9359470" id="uf9359470"><span data-lake-id="u1fdb9c63" id="u1fdb9c63">分库分表：当我们做分库分表的时候，就没办法依赖一张表的自增主键来做主键ID了，这样就会发生重复导致冲突的问题</span></li>
   <li fid="u291560ef" data-lake-id="u76e3dca9" id="u76e3dca9"><span data-lake-id="uc82c6f98" id="uc82c6f98">可预测：因为ID是顺序自增的，所以是可以预测的，这就给系统带来了一定的安全风险。</span></li>
   <li fid="u291560ef" data-lake-id="u9ad6e7b4" id="u9ad6e7b4"><span data-lake-id="ubef46216" id="ubef46216">可能用尽：自增id的话可能是int、bigint等，但是他们都是有范围的，有可能会用尽</span></li>
  </ul>
 </body>
</html>